package com.bytic.miaosha.controller;

import com.bytic.miaosha.annotation.AccessLimit;
import com.bytic.miaosha.constant.StatusConstant;
import com.bytic.miaosha.domain.MiaoshaMessage;
import com.bytic.miaosha.domain.MiaoshaOrder;
import com.bytic.miaosha.domain.MiaoshaUser;
import com.bytic.miaosha.domain.OrderInfo;
import com.bytic.miaosha.exception.GlobalException;
import com.bytic.miaosha.rabbitmq.MQSender;
import com.bytic.miaosha.redis.GoodsKey;
import com.bytic.miaosha.result.CodeMsg;
import com.bytic.miaosha.result.Result;
import com.bytic.miaosha.service.GoodsService;
import com.bytic.miaosha.service.MiaoshaService;
import com.bytic.miaosha.service.OrderService;
import com.bytic.miaosha.service.RedisService;
import com.bytic.miaosha.vo.GoodsVO;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/miaosha")
public class MiaoshaController implements InitializingBean {

    @Autowired
    private OrderService orderService;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private MiaoshaService miaoshaService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private MQSender mqSender;

    // 内存标记，减少 redis访问
    public Map<Long, Boolean> localMap = new HashMap<Long, Boolean>();

    /**
     * 初始化将秒杀数量加载到redis中
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVO> goods = goodsService.listGoodsVo();
        if (CollectionUtils.isEmpty(goods)) {
            return;
        }
        for (GoodsVO good : goods) {
            redisService.set(GoodsKey.goodStock, "" + good.getId(), good.getStockCount());
            localMap.put(good.getId(), false);
        }
    }

    /**
     * 1000 * 10
     * QPS: 457
     * @param model
     * @param user
     * @param goodsId
     * @return
     */
    /*@RequestMapping("/domiaosha")
    public String domiaosha(Model model, MiaoshaUser user, @RequestParam("goodsId") long goodsId) {
        if (user == null) { // 用户未登录
            return "login";
        }
        // 查看是否有库存
        GoodsVO goodsVO = goodsService.getGoodsVoByGoodsId(goodsId);
        if (goodsVO.getStockCount() <= 0) {
            model.addAttribute("errmsg", CodeMsg.MIAO_SHA_OVER.getMsg());
            return "miaosha_fail";
        }
        // 查看是否重复秒杀
        MiaoshaOrder miaoshaOrder = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
        if (miaoshaOrder != null) {
            model.addAttribute("errmsg", CodeMsg.REPEATE_MIAOSHA.getMsg());
            return "miaosha_fail";
        }
        // 减库存 下订单 写入秒杀订单 ----> 事务
        OrderInfo orderInfo = miaoshaService.miaosha(user, goodsVO);
        model.addAttribute("goods", goodsVO);
        model.addAttribute("orderInfo", orderInfo);
        return "order_detail";
    }*/

    /**
     * 页面静态化
     * @param model
     * @param user
     * @param goodsId
     * @return
     */
    /*@RequestMapping(value = "/domiaosha", method = RequestMethod.POST)
    public Result<OrderInfo> domiaosha(Model model, MiaoshaUser user, @RequestParam("goodsId") long goodsId) {
        if (user == null) { // 用户未登录
            throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
        }
        // 查看是否有库存
        GoodsVO goodsVO = goodsService.getGoodsVoByGoodsId(goodsId);
        if (goodsVO.getStockCount() <= 0) {
            throw new GlobalException(CodeMsg.MIAO_SHA_OVER);
        }
        // 查看是否重复秒杀
        MiaoshaOrder miaoshaOrder = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
        if (miaoshaOrder != null) {
            throw new GlobalException(CodeMsg.REPEATE_MIAOSHA);
        }
        // 减库存 下订单 写入秒杀订单 ----> 事务
        OrderInfo orderInfo = miaoshaService.miaosha(user, goodsVO);
        return Result.success(orderInfo);
    }*/

    /**
     * 获取秒杀接口
     *
     * @param user
     * @param goodsId
     * @return
     */
    // 防刷控制
    @AccessLimit(seconds=5, maxCount=5, needLogin=true)
    @RequestMapping(value = "/getMiaoshaPath", method = RequestMethod.GET)
    @ResponseBody
    public Result<String> getMiaoshaPath(MiaoshaUser user, @RequestParam("goodsId") long goodsId,
                                         @RequestParam(value = "verifyCode", defaultValue = "0") int verifyCode) {
        if (user == null) {
            throw new GlobalException(CodeMsg.SESSION_ERROR);
        }
        boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);
        if (!check) {
            throw new GlobalException(CodeMsg.REQUEST_ILLEGAL);
        }
        String path = miaoshaService.createMiaoshaPath(user, goodsId);
        return Result.success(path);
    }

    /**
     * 1. redis 预减库存
     * 2. 秒杀任务入队
     *
     * @param user
     * @param goodsId
     * @return
     */
    @RequestMapping(value = "/{path}/domiaosha", method = RequestMethod.POST)
    @ResponseBody
    public Result<Integer> domiaosha(MiaoshaUser user, @RequestParam("goodsId") long goodsId,
                                     @PathVariable("path") String path) {
        if (user == null) { // 用户未登录
            throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
        }
        // 验证path
        boolean checkPath = miaoshaService.checkMiaoshaPath(user, goodsId, path);
        if (!checkPath) {
            throw new GlobalException(CodeMsg.REQUEST_ILLEGAL);
        }
        //内存标记，减少redis访问
        Boolean isOver = localMap.get(goodsId);
        if (isOver) {
            throw new GlobalException(CodeMsg.MIAO_SHA_OVER);
        }
        // 预减库存
        Long stock = redisService.decr(GoodsKey.goodStock, "" + goodsId);
        if (stock < 0) {
            localMap.put(goodsId, true);
            throw new GlobalException(CodeMsg.MIAO_SHA_OVER);
        }
        // 查看是否重复秒杀
        MiaoshaOrder miaoshaOrder = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
        if (miaoshaOrder != null) {
            throw new GlobalException(CodeMsg.REPEATE_MIAOSHA);
        }
        // 入队
        MiaoshaMessage message = new MiaoshaMessage();
        message.setUser(user);
        message.setGoodsId(goodsId);
        mqSender.sendMiaoshaMessage(message);
        return Result.success(StatusConstant.QUEUING); // 排除中
    }

    @RequestMapping(value = "/result", method = RequestMethod.GET)
    @ResponseBody
    public Result<Long> getMiaoshaResult(MiaoshaUser user, @RequestParam("goodsId") long goodsId) {
        if (user == null) {
            throw new GlobalException(CodeMsg.SESSION_ERROR);
        }
        long result = miaoshaService.getMiaoshaResult(user.getId(), goodsId);
        return Result.success(result);
    }

    @RequestMapping(value = "/verifyCode", method = RequestMethod.GET)
    @ResponseBody
    public Result<String> verifyCode(HttpServletResponse response, MiaoshaUser user, @RequestParam("goodsId") long
            goodsId) {
        if (user == null) {
            throw new GlobalException(CodeMsg.SESSION_ERROR);
        }
        try {
            BufferedImage image = miaoshaService.createVerifyCode(user, goodsId);
            ServletOutputStream os = response.getOutputStream();
            ImageIO.write(image, "JPEG", os);
            os.flush();
            os.close();
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(CodeMsg.MIAOSHA_FAIL);
        }
    }
}
